//--------------Class SnapToElement------------------------------
ADF.util.SnapToElement = function() {
    ADF.util.SnapToElement.superclass.constructor.call(this);
}

var ThisClass = ADF.util.SnapToElement;

COM.util.defineClass(ThisClass, Object,{
	makeAbsolute : function(figure , t){
		figure.translateToAbsolute(t);
	},
	
	makeRelative : function(figure , t){
		figure.translateToRelative(t);
	},
	
	snapPoint : function(request , snapLocations , rects , result){
			var resultRect = new COM.draw2d.Rectangle();
			snapLocations = this.snapRectangleAll(request, snapLocations, rects, resultRect);
			result.x = result.x + resultRect.x;
			result.y = result.y + resultRect.y;
			return snapLocations;
	},
	
	snapRectangleAll : function(request , snapOrientation , baseRects , result){
		for (var i = 0; i < baseRects.length && snapOrientation != 0; i++)
			snapOrientation = this.snapRectangle(request, snapOrientation,
					baseRects[i], result);

		return snapOrientation;
	},
				
	getSnapBrother : function(baseRect , direction , target, request){
		var rect = baseRect.getCopy();
		this.result_h = null;
		this.result_v = null;
		this.min_h =  99999;
		this.min_v =  99999;
		var snapDistance = this.getSnapDistance();
		//�����������е�����ͼ��
		//host.getViewer._editParts
//		var editParts = this.host.getViewer()._editParts;
		var rootPart = this.host.getViewer().getRootEditPart();
		var editParts = new Array();
		editParts = this.getAllChildren(rootPart , editParts , target);
		var h_hasline = false;
		var v_hasline = false;
		var moveDelta = request.moveDelta;
		var resizeDelta = request.resizeDelta;
		for(var i =0 ; i < editParts.length ; i++){
			var figure = editParts[i].getFigure();
			var bounds = figure.getBounds().getCopy();
			this.makeAbsolute(figure, bounds);
			var distance;
			if ((direction &COM.draw2d.PositionConstants.EAST) != 0 || (direction &COM.draw2d.PositionConstants.WEST) != 0) {
				if (this.isMove || (!this.isMove && (direction &COM.draw2d.PositionConstants.WEST) != 0)) {
					var value= bounds.x -rect.x ;
					distance =this.getAbs(value);//ȡ����ֵ
					if (distance <= snapDistance && distance < this.min_h && !v_hasline) {
						min_h = distance;
						//Pare ����Map�洢��ֵ�Զ���
						this.result_h = new ADF.util.Pair(figure,COM.draw2d.PositionConstants.WEST);
						this.pt1 = rect.getTopLeft();
						this.pt2 = rect.getBottomLeft();
						w = rect.getTopLeft().x;
						if(moveDelta.x != 0){
							v_hasline = true;
						}
					}
					distance = this.getAbs(bounds.x + bounds.width - rect.x);
					
					if (distance <= snapDistance && distance < this.min_h && !v_hasline) {
						min_h = distance;
						this.result_h = new ADF.util.Pair(figure,COM.draw2d.PositionConstants.EAST);
						this.pt1 = rect.getTopLeft();
						this.pt2 = rect.getBottomLeft();
						if(moveDelta.x != 0){
							v_hasline = true;
						}
					}
				}
				if (this.isMove || (!this.isMove && (direction &COM.draw2d.PositionConstants.EAST) != 0)) {
					distance = this.getAbs(bounds.x - rect.x - rect.width);
					if (distance <= snapDistance && distance < this.min_h && !v_hasline) {
						min_h = distance;
						this.result_h = new ADF.util.Pair(figure,COM.draw2d.PositionConstants.WEST);
						this.pt1 = rect.getTopRight();
						this.pt2 = rect.getBottomRight();
						if(moveDelta.x == 0 && resizeDelta.width != 0){
							v_hasline = true;
						}
					}
					distance = this.getAbs(bounds.x + bounds.width - rect.x - rect.width);
					if (distance <= snapDistance && distance < this.min_h && !v_hasline) {
						min_h = distance;
						this.result_h = new ADF.util.Pair(figure,COM.draw2d.PositionConstants.EAST);
						this.pt1 = rect.getTopRight();
						this.pt2 = rect.getBottomRight();
						if(moveDelta.x == 0 && resizeDelta.width != 0){
							v_hasline = true;
						}
					}
				}
			}
			if ((direction & COM.draw2d.PositionConstants.NORTH) != 0 || (direction & COM.draw2d.PositionConstants.SOUTH) != 0) {
				if (this.isMove || (!this.isMove && (direction & COM.draw2d.PositionConstants.NORTH) != 0)) {
					distance = this.getAbs(bounds.y - rect.y);
					if (distance <= snapDistance && distance < this.min_v  && !h_hasline) {
						min_v = distance;
						this.result_v = new ADF.util.Pair(figure, COM.draw2d.PositionConstants.NORTH);
						this.pt3 = rect.getTopLeft();
						this.pt4 = rect.getTopRight();
						if(moveDelta.y != 0){
							h_hasline = true;
						}
					}
					distance = this.getAbs(bounds.y + bounds.height - rect.y);
					if (distance <= snapDistance && distance < this.min_v && !h_hasline) {
						min_v = distance;
						this.result_v = new ADF.util.Pair(figure, COM.draw2d.PositionConstants.SOUTH);
						this.pt3 = rect.getTopLeft();
						this.pt4 = rect.getTopRight();
						if(moveDelta.y != 0){
							h_hasline = true;
						}
					}
				}
				if (this.isMove || (!this.isMove && (direction & COM.draw2d.PositionConstants.SOUTH) != 0)) {
					distance = this.getAbs(bounds.y - rect.y - rect.height);
					if (distance <= snapDistance && distance < this.min_v && !h_hasline) {
						min_v = distance;
						this.result_v = new ADF.util.Pair(figure, COM.draw2d.PositionConstants.NORTH);
						this.pt3 = rect.getBottomLeft();
						this.pt4 = rect.getBottomRight();
						if(moveDelta.y == 0 && resizeDelta.height != 0){
							h_hasline = true;
						}
					}
					distance = this.getAbs(bounds.y + bounds.height - rect.y - rect.height);
					if (distance <= snapDistance && distance < this.min_v && !h_hasline) {
						min_v = distance;
						this.result_v = new ADF.util.Pair(figure, COM.draw2d.PositionConstants.SOUTH);
						this.pt3 = rect.getBottomLeft();
						this.pt4 = rect.getBottomRight();
						if(moveDelta.y == 0 && resizeDelta.height != 0){
							h_hasline = true;
						}
					}
				}
			}
		}
	},
	/**
	 * ��ȡ���е���EditPart
	 */
	getAllChildren : function(root , editparts , target){
		var children = root.getChildren();
		 for (var i =0 ; i < children.length ; i++){
			 if(children[i].getChildren().length != 0){
				 this.getAllChildren(children[i] , editparts);
			 }
			 if(!target){
				 target = this.host.getViewer().getSelection()[0];
			 }
			 
			//  if(!children[i].isEditable() 
			//  //	@TODO king
			// 		//  || children[i] instanceof UIEditor.DesignPanelContentEditPart 
			// 		 || children[i]._id == target._id
			// 		 || children[i].getParent().getFigure().getBounds().x == 10000)
			// 	 continue;
			 editparts.push(children[i]);
		 }
		 
		 return editparts;
	},
	
	
	/**
	 * ����ȫ�ֱ�����
	 */
	getSnapDistance : function(){
		return 5;
	},
	
	setHostPart : function(host){
		this.host = host;
	},
	
	getAbs : function(value){
		return (value < 0) ? -value : value;
	},
	
	snapRectangle : function(request, snapOrientation,
			baseRect , result , target){
		var direction = this.getDirection(request);
		this.pt1 = null;
		this.pt2 = null;
		this.pt3 = null;
		this.pt4 = null;
		this.getSnapBrother(baseRect, direction , target,request);
		this.eraseLineFeedback();
		this.handleHorizontal(baseRect, result, direction);
		this.handleVertical(baseRect, result, direction);
		return snapOrientation;
	},
	
	getDirection : function(request){
		var direction = 0;
		if (COM.gef.RequestConstants.REQ_ADD == request.getType()
				|| COM.gef.RequestConstants.REQ_CLONE == request.getType()
				|| COM.gef.RequestConstants.REQ_MOVE == request.getType()
				|| COM.gef.RequestConstants.REQ_MOVE_CHILDREN == request.getType()) {
			this.isMove = true;
			this.isCreate = false;
			direction = COM.draw2d.PositionConstants.NSEW;
		}
		if (COM.gef.RequestConstants.REQ_RESIZE == request.getType()
				|| COM.gef.RequestConstants.REQ_RESIZE_CHILDREN == request.getType()) {
			this.isMove = false;
			this.isCreate = false;
			direction = COM.draw2d.PositionConstants.NSEW;
		}
		if (COM.gef.RequestConstants.REQ_CREATE == request.getType()) {
			this.isMove = false;
			this.isCreate = true;
			var moveDelta = this.getDragMoveDelta();
			if (moveDelta != null) {
				if (moveDelta.width > 0) {
					direction |= COM.draw2d.PositionConstants.EAST;
				} else if (moveDelta.width < 0) {
					direction |= COM.draw2d.PositionConstants.WEST;
				}
				if (moveDelta.height > 0) {
					direction |= COM.draw2d.PositionConstants.SOUTH;
				} else if (moveDelta.height < 0) {
					direction |= COM.draw2d.PositionConstants.NORTH;
				}
			}
		}
		if (COM.gef.RequestConstants.REQ_PASTE == request.getType()) {
			
		}
		return direction;
 },
	
	handleHorizontal : function(baseRect, result, direction){
		if (this.pt1 == null || this.pt2 == null) {
			return;
		}
		var startPoint = null;
		var endPoint = null;
		if (this.result_h != null && this.result_h.getKey() != null) {
			var figure = this.result_h.getKey();
			var b = figure.getBounds().getCopy();
			this.makeAbsolute(figure, b);
			var p1 = null;
			var p2 = null;
			var border = this.result_h.getValue();
			switch (border) {
			case COM.draw2d.PositionConstants.EAST:
				p1 = b.getTopRight();
				p2 = b.getBottomRight();
				break;
			case COM.draw2d.PositionConstants.WEST:
				p1 = b.getTopLeft();
				p2 = b.getBottomLeft();
				break;
				
			default :
				break;
			}
			if (p1 == null || p2 == null) {
				return;
			}
			if ((direction &COM.draw2d.PositionConstants.WEST) != 0) {
				if (this.isCreate) {
					result.x = result.x + p1.x - this.pt1.x;
				} else {
					result.x = p1.x - this.pt1.x;
				}
				if (!this.isMove) {
					result.width = result.width + this.pt1.x - p1.x;
				}
				startPoint = new COM.draw2d.Point(p1.x, this.getMin(this.pt1.y, this.pt2.y, p1.y, p2.y));
				endPoint = new COM.draw2d.Point(p1.x, this.getMax(this.pt1.y,this. pt2.y, p1.y, p2.y));
			}
			if ((direction &COM.draw2d.PositionConstants.EAST) != 0) {
				if (this.isMove) {
					if (this.isCreate) {
						result.x = result.x + p1.x - this.pt1.x;
					} else {
						result.x = p1.x - this.pt1.x;
					}
				} else {
					result.width = result.width + p1.x - this.pt1.x;
				}
				startPoint = new COM.draw2d.Point(p1.x, this.getMin(this.pt1.y, this.pt2.y, p1.y, p2.y));
				endPoint = new COM.draw2d.Point(p1.x, this.getMax(this.pt1.y, this.pt2.y, p1.y, p2.y));
			}
		}
		if (startPoint != null && endPoint != null) {
			this.addLineFeedback(startPoint, endPoint , this.host);
		}
	},
	
	handleVertical : function(baseRect, result, direction){
		if (this.pt3 == null || this.pt4 == null) {
			return;
		}
		var startPoint = null;
		var endPoint = null;
		if (this.result_v != null && this.result_v.getKey() != null) {
			var figure = this.result_v.getKey();
			var b = figure.getBounds().getCopy();
			this.makeAbsolute(figure, b);
			var p1 = null;
			var p2 = null;
			var border = this.result_v.getValue();
			switch (border) {
			case COM.draw2d.PositionConstants.NORTH:
				p1 = b.getTopLeft();
				p2 = b.getTopRight();
				break;
			case COM.draw2d.PositionConstants.SOUTH:
				p1 = b.getBottomLeft();
				p2 = b.getBottomRight();
				break;
			default :
				break ;
		
			}
			if (p1 == null || p2 == null) {
				return;
			}
			if ((direction & COM.draw2d.PositionConstants.NORTH) != 0) {
				if (this.isCreate) {
					result.y = result.y + p1.y - this.pt3.y;
				} else {
					result.y = p1.y - this.pt3.y;
				}
				if (!this.isMove) {
					result.height = result.height + this.pt3.y - p1.y;
				}
				startPoint = new COM.draw2d.Point(this.getMin(this.pt3.x, this.pt4.x, p1.x, p2.x), p1.y);
				endPoint = new COM.draw2d.Point(this.getMax(this.pt3.x, this.pt4.x, p1.x, p2.x), p1.y);
			}
			if ((direction & COM.draw2d.PositionConstants.SOUTH) != 0) {
				if (this.isMove) {
					if (this.isCreate) {
						result.y = result.y + p1.y - this.pt3.y;
					} else {
						result.y = p1.y - this.pt3.y;
					}
				} else {
					result.height = result.height + p1.y - this.pt3.y;
				}
				startPoint = new COM.draw2d.Point(this.getMin(this.pt3.x, this.pt4.x, p1.x, p2.x), p1.y);
				endPoint = new COM.draw2d.Point(this.getMax(this.pt3.x, this.pt4.x, p1.x, p2.x), p1.y);
			}
		}
		if (startPoint != null && endPoint != null) {
			this.addLineFeedback(startPoint, endPoint , this.host);
		}
	},
	
	getMax : function(v1 ,v2 , v3 , v4){
			var result = v1;
			if(v2 > result)
				result = v2;
			if(v3 > result)
				result = v3;
			if(v4 > result)
				result = v4;
			return result ;
	},
	
	getMin : function(v1 ,v2 , v3 , v4){
		var result = v1;
		if(v2 < result)
			result = v2;
		if(v3 < result)
			result = v3;
		if(v4 < result)
			result = v4;
		return result ;
	},
	
	addLineFeedback : function(startPoint, endPoint ,host){
		this.editpolicy.addLineFeedback(startPoint, endPoint , host);
	},
	
	eraseLineFeedback : function(){
		this.editpolicy.eraseLineFeedback(this.host);
	},
	
	getEditpolicy : function(){
		return this.editpolicy;
	},
	
	setEditpolicy : function(editpolicy){
		this.editpolicy = editpolicy;
	},
	
	getDragMoveDelta : function(){
		this.host.getViewer().getBench().getActiveTool().getDragMoveDelta();
	}
	
});
